

#include "DLMsgQueue.h"
#include "cc_pub.h"
// #include "basic_api.h"
#include "cc_malloc.h"		// 依赖 malloc/free 
#include "Macro_DLink.h"	// 宏
// #include "GDLink.h"			// tDLQNode 定义

#define CFG_RWLOCK_CHECK 

#define LLOG
#define LLOG_ERR
#define LLOG_MARK
#include "llog.h"

#ifdef	CFG_SYS_MALLOC

#define L_MALLOC 	MALLOC
#define L_FREE 		MFREE

#else

#include <stdlib.h>
#define L_MALLOC(A) malloc(A)
#define L_FREE(A)	free(A)

#endif


/********* interior  struct **********/
// 与 tDLQNode 相同，此处独立定义 是为了减少依赖；
typedef struct CC_DLink_Queue_Node tDLQNode;
struct CC_DLink_Queue_Node{
    struct CC_DLink_Queue_Node* pPrev; //前
    struct CC_DLink_Queue_Node* pNext; //后
};


struct CC_Double_Link_Msg_Queue{
	tDLQNode* pHead;
	uint32_t ItemNum ;
	uint16_t RCnt;
	uint8_t  RWLock;
};

/******* global val ***************/

/******* local function **************/

/******* TODO ************************/

#ifdef CFG_DLMSG_QUEUE

void DLMsgQueue_ShowObj(tDLMsgQueue* pObj){
    LLOG("tDLMsgQueue\n");
	LLOG("pHead	  =[%x]\n",pObj->pHead	);
	LLOG("ItemNum =[%d]\n",pObj->ItemNum);
	LLOG("RWLock  =[%d]\n",pObj->RWLock	);	
	LLOG("RCnt  =[%d]\n",pObj->RCnt	);	
}

tDLMsgQueue* DLMsgQueue_Create(uint32_t ItemNum){
	
	uint32_t ItemSz;
	tDLMsgQueue* ptmp = NULL;
		
	ptmp = (tDLMsgQueue*)L_MALLOC(sizeof(tDLMsgQueue));
	if(ptmp == NULL){
		LLOG_ERR();
		return ptmp;
	}
	
	MEMSET((uint8_t*)ptmp,0,sizeof(tDLMsgQueue));
	ptmp->ItemNum = ItemNum; 

	return ptmp;
}

uint32_t DLMsgQueue_Write(tDLMsgQueue* pObj, uint32_t dLen, uint8_t* pPkg){

	uint8_t* ptmp = NULL;
	tDLQNode* pDLNode = NULL;
    uint32_t CopySz;
    
	CopySz=0;

	if(pObj == NULL) 		{ LLOG_ERR(); return CopySz;}
	if(pPkg == NULL) 		{ LLOG_ERR(); return CopySz;}
	if(dLen == 0) 			{ LLOG_ERR(); return CopySz;}

	#if CC_BFIFO_RWLOCK_OC
	if(pObj->RWLock != 0){
		return CopySz;
	}
	#endif
	
	pObj->RWLock = 1; 

	if(pObj->ItemNum > 0){
		if( pObj->RCnt >= pObj->ItemNum){
			pObj->RWLock=0;
			CopySz = 0;
			LLOG_ERR();
			return CopySz;		
		}
	}
	//
	ptmp = L_MALLOC(dLen+sizeof(uint32_t)+sizeof(tDLQNode));
	if(ptmp == NULL){
		pObj->RWLock=0;
		CopySz = 0;
		LLOG_ERR();
		return CopySz;
	}
	
	pDLNode = (tDLQNode*)ptmp;
	// LLOG("#I ptmp [0x%x]\n",ptmp);
	ptmp += sizeof(tDLQNode);		
	*((uint32_t*)ptmp) = dLen;
	// LLOG("#I ptmp [0x%x] len[%d]\n",ptmp,*((uint32_t*)ptmp));

	MEMCPY(&ptmp[sizeof(uint32_t)],pPkg,dLen);
	CopySz = dLen;
	
	do{ // add to head;
		tDLQNode* pFrist;
		if(pObj->pHead == NULL){ 
			GDLNODE_INSERT_LOOPHEAD(pObj->pHead,pDLNode);
		}
		else{
			pFrist = pObj->pHead;
			GDLNODE_INSERT_BEFORE(pObj->pHead,pFrist,pDLNode);
		}
		pObj->RCnt++;
	}while(0);
	
	//
	pObj->RWLock=0;
    return CopySz;
}

uint32_t DLMsgQueue_Read(tDLMsgQueue* pObj,uint32_t RBufSz, uint8_t* pRBuf){

	uint8_t* ptmp = NULL;
    uint32_t CopySz;
    
	CopySz=0;
	if(pObj == NULL) 		{ LLOG_ERR(); return CopySz;}
	if(pRBuf == NULL) 		{ LLOG_ERR(); return CopySz;}
	if(RBufSz == 0) 		{ LLOG_ERR(); return CopySz;}
	
	#if CC_BFIFO_RWLOCK_OC
	if(pObj->RWLock != 0){
		return CopySz;
	}
	#endif
	pObj->RWLock = 1;
	
	if(pObj->pHead == NULL){	
		LLOG_ERR();
		pObj->RWLock=0;
		return CopySz;
	}

	ptmp = (uint8_t*)pObj->pHead->pPrev;
	
	do{// 出队
		tDLQNode* pTail = NULL;
		pTail = pObj->pHead->pPrev;
		GDLNODE_REMOVE(pObj->pHead,pTail);
		
		if(pObj->RCnt > 0){
			pObj->RCnt--;
		}
		else{
			LLOG_ERR();
		}
	}while(0);
	// 
	ptmp += sizeof(tDLQNode);
	// LLOG("#I Read ptmp=0x%x \n",ptmp);
	CopySz = *((uint32_t*)ptmp);
	CopySz = (RBufSz > CopySz)?CopySz:RBufSz;
	MEMCPY(pRBuf,&ptmp[sizeof(uint32_t)],CopySz);
	
	ptmp -= sizeof(tDLQNode);
	L_FREE(ptmp);

	pObj->RWLock=0;
    return CopySz;
}

uint32_t DLMsgQueue_Reset(tDLMsgQueue* pObj){

	uint8_t* ptmp = NULL;
    uint32_t i;
    uint32_t CopySz;
    
	CopySz=0;
	if(pObj == NULL) 		{ LLOG_ERR(); return CopySz;}
	
	#if CC_BFIFO_RWLOCK_OC
	if(pObj->RWLock != 0){
		return CopySz;
	}
	#endif
	pObj->RWLock = 1; 
	
	while(pObj->pHead != NULL){
		
		ptmp = (uint8_t*)pObj->pHead->pPrev;
		
		do{// 出队
			tDLQNode* pTail = NULL;
			pTail = pObj->pHead->pPrev;
			GDLNODE_REMOVE(pObj->pHead,pTail);
			
			if(pObj->RCnt > 0){
				pObj->RCnt--;
			}
			else{
				LLOG_ERR();
			}
		}while(0);
		// 
		L_FREE(ptmp);
		CopySz++;
	}
	
	pObj->RWLock=0;
    return CopySz;
}

uint32_t DLMsgQueue_GetNextPkgSz(tDLMsgQueue* pObj){

	uint8_t* ptmp = NULL;
    uint32_t CopySz;
    
	CopySz=0;
	if(pObj == NULL) 		{ LLOG_ERR(); return CopySz;}
	
	#if CC_BFIFO_RWLOCK_OC
	if(pObj->RWLock != 0){
		return CopySz;
	}
	#endif
	pObj->RWLock = 1;
	
	if(pObj->pHead == NULL){	
		LLOG_ERR();
		pObj->RWLock=0;
		return CopySz;
	}

	ptmp = (uint8_t*)pObj->pHead->pPrev;
	ptmp += sizeof(tDLQNode);
	CopySz = *((uint32_t*)ptmp);

	pObj->RWLock=0;
    return CopySz;
	
}

uint32_t DLMsgQueue_Peek(tDLMsgQueue* pObj,uint32_t RBufSz, uint8_t* pRBuf){


	uint8_t* ptmp = NULL;
    uint32_t CopySz;
    
	CopySz=0;
	if(pObj == NULL) 		{ LLOG_ERR(); return CopySz;}
	if(pRBuf == NULL) 		{ LLOG_ERR(); return CopySz;}
	if(RBufSz == 0) 		{ LLOG_ERR(); return CopySz;}
	
	#if CC_BFIFO_RWLOCK_OC
	if(pObj->RWLock != 0){
		return CopySz;
	}
	#endif
	pObj->RWLock = 1;
	
	if(pObj->pHead == NULL){	
		LLOG_ERR();
		pObj->RWLock=0;
		return CopySz;
	}

	ptmp = (uint8_t*)pObj->pHead->pPrev;
	ptmp += sizeof(tDLQNode);
	
	CopySz = *((uint32_t*)ptmp);
	CopySz = (RBufSz > CopySz)?CopySz:RBufSz;
	MEMCPY(pRBuf,&ptmp[sizeof(uint32_t)],CopySz);
	
	pObj->RWLock=0;
    return CopySz;
}

uint32_t DLMsgQueue_DorpOne(tDLMsgQueue* pObj){

	uint8_t* ptmp = NULL;
    uint32_t CopySz;
    
	CopySz=0;
	if(pObj == NULL) 		{ LLOG_ERR(); return CopySz;}

	#if CC_BFIFO_RWLOCK_OC
	if(pObj->RWLock != 0){
		return CopySz;
	}
	#endif
	pObj->RWLock = 1;
	
	if(pObj->pHead == NULL){	
		LLOG_ERR();
		pObj->RWLock=0;
		return CopySz;
	}

	ptmp = (uint8_t*)pObj->pHead->pPrev;
	
	do{// 出队
		tDLQNode* pTail = NULL;
		pTail = pObj->pHead->pPrev;
		GDLNODE_REMOVE(pObj->pHead,pTail);
		
		if(pObj->RCnt > 0){
			pObj->RCnt--;
		}
		else{
			LLOG_ERR();
		}
	}while(0);
	// 
	ptmp += sizeof(tDLQNode);
	CopySz = *((uint32_t*)ptmp);
	ptmp -= sizeof(tDLQNode);
	L_FREE(ptmp);

	pObj->RWLock=0;
    return CopySz;
}

#endif

